/*
 * Copyright (c) 2013-2013 XXXX XXXXXX, Inc.
 * XXXX Road, XXXX, XXXX State, XXXX Post code, XXXX Country.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of XXXX
 * XXXXXX, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with XXXX.
 * 
 * History
 * Date        Ver Author        Change Description
 * ----------- --- ------------- ----------------------------------------
 * 03 May 2013 001 Karl          Create
 * 14 May 2013 002 Karl          Enter my account page.
 * 13 Jun 2013 003 Karl          Create method to add item to a list
 * 19 Jun 2013 004 Karl          Enter browse page.
 * 15 Jul 2013 005 Karl          A confirmation alert shown before enter help 
 *                               page. Update test script to handle it.
 */
package com.selenium.test.cases.pages.edu.pageUtil;

import static com.selenium.test.cases.pages.rcl.HomePage.HP_DIV_ADVANCED_SEARCH_BUTTON;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_DIV_BROWSE_BUTTON;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_INPUT_QUICK_SEARCH;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_LINK_ABOUT;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_LINK_HELP;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_LINK_HOME;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_LINK_LIST;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_LINK_LOGOUT;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_LINK_MY_ACCOUNT;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_QUICK_SEARCH_BY_ALL;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_SELECT_QUICK_SEARCH_BY;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_SPAN_QUICK_SEARCH_BUTTON;
import static com.selenium.test.cases.pages.rcl.HomePage.HP_TEXT_SEARCH_TYPE;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Set;

import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;

import com.selenium.test.cases.pages.rcl.AboutPage;
import com.selenium.test.cases.pages.rcl.AdvancedSearchPage;
import com.selenium.test.cases.pages.rcl.BrowsePage;
import com.selenium.test.cases.pages.rcl.HelpPage;
import com.selenium.test.cases.pages.rcl.HomePage;
import com.selenium.test.cases.pages.rcl.MyAccountAuthenticationPage;
import com.selenium.test.cases.pages.rcl.MyAccountPage;
import com.selenium.test.cases.pages.rcl.SearchResultListPage;
import com.selenium.test.cases.pages.rcl.SearchResultListPage.IsbnAndPrice;
import com.selenium.test.cases.pages.rcl.StaffListPage;
import com.selenium.test.util.ISeleniumUtil;

public class HomePageUtil {
	
	ISeleniumUtil seleniumUtil;
	HomePage homePage;
	
	public HomePageUtil(ISeleniumUtil seleniumUtil, 
			HomePage homePage){
		this.seleniumUtil = seleniumUtil;
		this.homePage = homePage;
	}
	
	public HomePage refreshHomePage(){
		seleniumUtil.click(seleniumUtil.findElement(HP_LINK_HOME));
		return new HomePage(seleniumUtil);
	}
	
	/**
	 * Enter My Account page when no authentication is needed.
	 * */
	public StaffListPage enterListPage(){
		WebElement listLink = seleniumUtil.findElement(HP_LINK_LIST);
		seleniumUtil.waitForFixedMilliseconds(6000);
		seleniumUtil.click(listLink);
		return new StaffListPage(seleniumUtil);
	}
	
	private MyAccountAuthenticationPage enterMyAccountAuthenticationPage(){
		seleniumUtil.click(seleniumUtil.findElement(HP_LINK_MY_ACCOUNT));
		return new MyAccountAuthenticationPage(seleniumUtil);
	}
	
	/**
	 * Enter My Account Page. 
	 * 
	 * History
	 * ----------- --- ------------- ----------------------------------------
	 * 14 May 2013 002 Karl          Enter my account page.
	 * */
	public MyAccountPage enterMyAccountPage(){
		WebElement adminLnk = seleniumUtil.findElement(HP_LINK_MY_ACCOUNT);
		seleniumUtil.click(adminLnk);
		return new MyAccountPage(seleniumUtil);
	}
	
	/**
	 * Enter My Account page when authentication is needed, use the username and password
	 * to login.
	 * */
	public MyAccountPage enterMyAccountPage(String adminUsername, String adminPassword){
		MyAccountAuthenticationPage authenPage = enterMyAccountAuthenticationPage();
		return new MyAccountAuthenticationPageUtil(seleniumUtil, authenPage)
			.login(adminUsername, adminPassword);
	}
	

	public AdvancedSearchPage enterAdvancedSearchPage(){
		WebElement advancedSearchButton = seleniumUtil.findElement(HP_DIV_ADVANCED_SEARCH_BUTTON);
		seleniumUtil.click(advancedSearchButton);
		return new AdvancedSearchPage(seleniumUtil);
	}
	
	/**
	 * Assume current page is home page, click help page link to goto help page.
	 * Current page will be changed to help page. 
	 * 
	 * History
	 * Date        Ver Author        Change Description
	 * ----------- --- ------------- ----------------------------------------
	 * 15 Jul 2013 005 Karl          A confirmation alert shown before enter help 
	 *                               page. Update test script to handle it.
	 * */
	public HelpPage gotoHelpPage(){
		// get currently opened browsers
		Set<String> before = seleniumUtil.getWindowHandles();
		
		// make sure log in first and then click Books In Print Help link
		try {
			seleniumUtil.click(seleniumUtil.findElement(HP_LINK_HELP));
			seleniumUtil.switchToAlert().accept();
		} catch(NoAlertPresentException e){
			// it's fine if no alert present
		}
		
		seleniumUtil.switchToPromptedWindowAfterWait(before, 2000);
		return new HelpPage(seleniumUtil);
	}
	
	public AboutPage gotoAboutPage(){
		// get currently opened browsers
		Set<String> before = seleniumUtil.getWindowHandles();
		
		try {
			seleniumUtil.click(seleniumUtil.findElement(HP_LINK_ABOUT));
			seleniumUtil.switchToAlert().accept();
		} catch(NoAlertPresentException e){
			// it's fine if no alert present
		}
		
		seleniumUtil.switchToPromptedWindowAfterWait(before, 2000);
		return new AboutPage(seleniumUtil);
	}
	
	/**
	 * History
	 * Date        Ver Author        Change Description
	 * ----------- --- ------------- ----------------------------------------
	 * 19 Jun 2013 004 Karl          Enter browse page.
	 * */
	public BrowsePage enterBrowsePage(){
		seleniumUtil.waitForFixedMilliseconds(1000);
		seleniumUtil.click(seleniumUtil.findElement(HP_DIV_BROWSE_BUTTON));
		return new BrowsePage(seleniumUtil);
	}
	
	public SearchResultListPage quickSearch(String keyword){
		return quickSearch(keyword, HP_QUICK_SEARCH_BY_ALL);
	}
	
	public SearchResultListPage quickSearch(String keyword, String keywordType){
		// enter keyword and press search
		final WebElement keywordInput = seleniumUtil.findElement(HP_INPUT_QUICK_SEARCH);
		WebElement searchBtn = seleniumUtil.findElement(HP_SPAN_QUICK_SEARCH_BUTTON);
		if(!HP_QUICK_SEARCH_BY_ALL.equals(keywordType)){
			//the search type drop down list is a dynamic one, use following special steps to perform test
			WebElement triggerDrop = seleniumUtil.findElement(HP_TEXT_SEARCH_TYPE);
		    seleniumUtil.click(triggerDrop);
			seleniumUtil.select(new Select(seleniumUtil.findElement(HP_SELECT_QUICK_SEARCH_BY)), keywordType);
			seleniumUtil.click(triggerDrop);
		}
		seleniumUtil.clear(keywordInput);
		//in order to ensure input box clear completely.
		final int waitSeconds = 10000;
		seleniumUtil.waitForExepectedConditionUntilTimeOutInMilliseconds(
				new ExpectedCondition<Boolean>(){

					@Override
					public Boolean apply(WebDriver arg0) {
						return keywordInput.getText().equals("");
					}
					
				}
				, waitSeconds, "the input box didn't clear.");
		seleniumUtil.sendKeys(keywordInput,	keyword);
		seleniumUtil.click(searchBtn);
		return new SearchResultListPage(seleniumUtil);
	} 
	
	/** 
	 * Assume current page is home page, for each ISBN and price record, do a quick search to find that 
	 * record and then check that record. After all ISBN and price record are handled, use them to create 
	 * a new staff list.
	 *  
	 * NOTE: After this page is called, staff list page will be shown.
	 * 
	 * History
	 * Date        Ver Author        Change Description
	 * ----------- --- ------------- ----------------------------------------
	 * 13 Jun 2013 003 Karl          Create method to add item to a list
	 */
	public SearchResultListPage createStaffListByIsbnAndPrices(List<IsbnAndPrice> isbnAndPrices, 
			String newListName){
		if(isbnAndPrices == null || isbnAndPrices.size() == 0){
			throw new IllegalArgumentException("isbnAndPrice list is empty.");
		}
		
		SearchResultListPage resultListPage = null;
		SearchResultListPageUtil resultListPageUtil = null; 
				
		// check record one by one
		for(IsbnAndPrice loopIsbnAndPrice : isbnAndPrices){
			// find record one by one
			resultListPage = quickSearch(loopIsbnAndPrice.getIsbn());
			resultListPageUtil = new SearchResultListPageUtil(seleniumUtil, resultListPage);
			assertTrue("When creating a staff list, it is not able find any record with isbn as [" + 
				loopIsbnAndPrice.getIsbn() + "], please make sure you use correct ISBN number.", 
				resultListPage.isRecordExist());
			
			WebElement checkbox = null; 
			try{
				checkbox = resultListPage.getOneResultCheckboxByPrice(loopIsbnAndPrice.getPrice());
				seleniumUtil.click(checkbox);
			} catch( NoSuchElementException e){
				throw new NoSuchElementException("When creating a staff list, it is not able find any record with isbn [" + loopIsbnAndPrice.getIsbn() + "] and price [" + loopIsbnAndPrice.getPrice() + "], please make sure you use correct ISBN & price.");
			}
		}
		
		// use record to create a new list
		resultListPageUtil.addCheckedRecordsToNewList(newListName);
		return new SearchResultListPage(seleniumUtil);
		
	}
	
	/** 
	 * Assume current page is home page, do a quick search by keyword, and select some records according to 
	 * the ISBN and price list, then create a new staff list. 
	 * 
	 * @param keyword used to do a quick search.
	 * @param isbnAndPrices sub set of records on current page after do a quick search by keyword.
	 * 
	 * History
	 * Date        Ver Author        Change Description
	 * ----------- --- ------------- ----------------------------------------
	 */
	/*public SearchResultListPage createStaffListByQuickSearch(String keyword, List<IsbnAndPrice> isbnAndPrices, 
		String listName){
		
		if(isbnAndPrices == null || isbnAndPrices.size() == 0){
			throw new IllegalArgumentException("isbnAndPrice list is empty.");
		}
		
		SearchResultListPage resultListPage = quickSearch(keyword);
		SearchResultListPageUtil searchListUtil = 
			new SearchResultListPageUtil(seleniumUtil, resultListPage);
		searchListUtil.assertAtLeastOneDetailRecord();
		
		// check record one by one
		for(IsbnAndPrice loopIsbnAndPrice : isbnAndPrices){
			searchListUtil.selectByIsbnAndPrice(loopIsbnAndPrice);
		}
		
		// click add to list
		return searchListUtil.createNewListByCurrentSelectedRecords(listName);
	}*/
	
	public SearchResultListPage createStaffListByQuickSearchSelectAll(
		String keyword, String listName){
		SearchResultListPage resultListPage = quickSearch(keyword);
		SearchResultListPageUtil searchListUtil = 
			new SearchResultListPageUtil(seleniumUtil, resultListPage);
		searchListUtil.assertAtLeastOneDetailRecord();
		// click add to list
		return searchListUtil.createStaffListByCurrentResult(listName);
	}
	
	public void logout(){
		// Java script error occurs, temporarily wait a time period 
		seleniumUtil.waitForFixedMilliseconds(2000);
		
		// if logout link exists
		if(seleniumUtil.findElements(HP_LINK_LOGOUT).size() > 0 && 
			seleniumUtil.findElement(HP_LINK_LOGOUT).isDisplayed()){
			WebElement logoutLink = seleniumUtil.findElement(HP_LINK_LOGOUT);
			logoutLink.click();
			seleniumUtil.waitForPageToLoad();
		}
	}
}
